home *** CD-ROM | disk | FTP | other *** search
/ The Programmer Disk / The Programmer Disk (Microforum).iso / xpro / extra / pro13 / format.c < prev    next >
C/C++ Source or Header  |  1993-07-01  |  7KB  |  370 lines

  1. /*
  2.     format.C
  3.  
  4.     Format function used by v_cprintf () and sprintf ().
  5.  
  6.     Copyright (C) 1993, Geoff Friesen B.Sc.
  7.     All rights reserved.
  8. */
  9.  
  10. #define INCL_FORMAT
  11.  
  12. void _prt10    (unsigned num, char *str);
  13. void _prt16    (unsigned num, char *str, int hexcase);
  14. void _prtl10    (unsigned long num, char *str);
  15. void _prtl16    (unsigned long num, char *str, int hexcase);
  16.  
  17. int pascal format (void (*func) (int), const char *fmt, void *ap)
  18. {
  19.    int c;        /* current character in format string */
  20.    int i;        /* loop index */
  21.    int sign;        /* sign character for positive numeric output */
  22.    char fill;        /* fill character (' ' or '0') */
  23.    int width;        /* field width specifier */
  24.    char *str;        /* running pointer */
  25.    int digit1;        /* offset to add to first numeric digit */
  26.    int length;        /* length of string "str" */
  27.    int leading;        /* # of leading/trailing fill characters */
  28.    int hexcase;        /* upper/lower-case hex digits flag */
  29.    int leftjust;    /* 0 = right-justified else left-justified */
  30.    int longflag;    /* not zero for long numerics */
  31.    int count = 0;    /* current number of characters output */
  32.    char *percent;    /* location of most recent percent sign */
  33.    char string [20];    /* temporary buffer */
  34.  
  35.    /* ---------------------------------------- */
  36.    /* Echo literals and formatted data to func */
  37.    /* ---------------------------------------- */
  38.  
  39.    for (;;)
  40.    {
  41.     /* -------------------------------- */
  42.     /* Initialize variables to defaults */
  43.     /* -------------------------------- */
  44.  
  45.     sign = ' ';      /* positive characters begin with ' ' */
  46.     fill = ' ';    /* fill character is ' ' */
  47.     width = 0;    /* width of field */
  48.     hexcase = 'L';    /* assume lower-case hex digits */
  49.     leftjust = 0;    /* numbers are right-justified */
  50.     longflag = 0;    /* numbers are interpreted as ints */
  51.  
  52.     /* -------------------------------------------- */
  53.     /* Echo literals until '%' or end of fmt string */
  54.     /* -------------------------------------------- */
  55.  
  56.     while ((c = *fmt++) != '%')
  57.     {
  58.        if (!c)
  59.            return count;    /* return if end of format string */
  60.  
  61.        (*func) (c);
  62.        count++;
  63.     }
  64.  
  65.     /* ---------------------- */
  66.     /* Obtain location of '%' */
  67.     /* ---------------------- */
  68.  
  69.     percent = (char *) fmt-1;
  70.  
  71.     /* ---------------- */
  72.     /* Echo "%%" as '%' */
  73.     /* ---------------- */
  74.  
  75.     if (*fmt == '%')
  76.     {
  77.         (*func) (*fmt++);
  78.         count++;
  79.         continue;
  80.     }
  81.  
  82.     /* ------------------------------------------------------- */
  83.     /* Handle format specification: % [flags] [width] [l] type */
  84.     /* ------------------------------------------------------- */
  85.  
  86.     /* ----------------- */
  87.     /* 1. Handle [flags] */
  88.     /* ----------------- */
  89.  
  90.     while ((c = *fmt) == '+' || c == '-')
  91.     {
  92.        switch (c)
  93.        {
  94.           case '+': sign = '+';
  95.             break;
  96.  
  97.           case '-': leftjust = 1;
  98.        }
  99.  
  100.        fmt++;
  101.     }
  102.  
  103.     /* -------------- */
  104.     /* Handle [width] */
  105.     /* -------------- */
  106.  
  107.     fill = (*fmt == '0') ? *fmt++ : ' ';
  108.  
  109.     if (*fmt == '*')
  110.     {
  111.         width = *((int *) ap)++;
  112.         fmt++;
  113.     }
  114.     else
  115.         while ('0' <= *fmt && *fmt <= '9')
  116.            width = width*10+*fmt++-'0';
  117.  
  118.     /* ---------- */
  119.     /* Handle [l] */
  120.     /* ---------- */
  121.  
  122.     if (*fmt == 'l')
  123.     {
  124.         longflag = 1;
  125.         fmt++;
  126.     }
  127.  
  128.     /* ----------- */
  129.     /* Handle type */
  130.     /* ----------- */
  131.  
  132.     str = string;
  133.  
  134.     switch (*fmt++)
  135.     {
  136.        case 'c' : string [0] = *(int *) ap;
  137.               string [1] = '\0';
  138.  
  139.               fill = ' ';
  140.  
  141.               ((int *) ap)++;
  142.  
  143.               if (sign == '+')
  144.               sign = ' ';
  145.  
  146.               break;
  147.  
  148.        case 's' : str = *(char **) ap;
  149.  
  150.               fill = ' ';
  151.  
  152.               ((char **) ap)++;
  153.  
  154.               if (sign == '+')
  155.               sign = ' ';
  156.  
  157.               break;
  158.  
  159.        case 'd' :
  160.        case 'i' : if (longflag)
  161.               {
  162.               if (*(long *) ap < 0)
  163.               {
  164.                   sign = '-';
  165.                   *(long *) ap = -*(long *) ap;
  166.               }
  167.               }
  168.               else
  169.               if (*(int *) ap < 0)
  170.               {
  171.                   sign = '-';
  172.                   *(int *) ap = -*(int *) ap;
  173.               }
  174.  
  175.        case 'u' : if (longflag)
  176.               {
  177.               digit1 = '\0';
  178.               while (*(long *) ap < 0)
  179.               {
  180.                  *(long *) ap -= 1000000000L;
  181.                  ++digit1;
  182.               }
  183.               _prtl10 (*(unsigned long *) ap, str);
  184.               ((unsigned long *) ap)++;
  185.               str [0] += digit1;
  186.               }
  187.               else
  188.               {
  189.               _prt10 (*(unsigned *) ap, str);
  190.               ((unsigned *) ap)++;
  191.               }
  192.  
  193.               break;
  194.  
  195.        case 'X' : hexcase = 'U';
  196.  
  197.        case 'x' : if (longflag)
  198.               {
  199.               _prtl16 (*(unsigned long *) ap, str, hexcase);
  200.               ((unsigned long *) ap)++;
  201.               }
  202.               else
  203.               {
  204.               _prt16 (*(unsigned *) ap, str, hexcase);
  205.               ((unsigned *) ap)++;
  206.               }
  207.  
  208.               if (sign == '+')
  209.               sign = ' ';
  210.               break;
  211.  
  212.         default : while (*percent)
  213.               {
  214.              (*func) (*percent++);
  215.              count++;
  216.               }
  217.               return count;
  218.     }
  219.  
  220.     for (length = 0; str [length] != '\0'; length++)
  221.          ;
  222.  
  223.     if (width < 0 || width > 80)
  224.         width = 0;
  225.  
  226.     leading = 0;
  227.     if (width)
  228.     {
  229.         if (length > width)
  230.         length = width;
  231.  
  232.         leading = width-length;
  233.  
  234.         if (sign == '-' || sign == '+')
  235.         --leading;
  236.     }
  237.  
  238.     if ((sign == '-' || sign == '+') && fill == '0')
  239.     {
  240.         (*func) (sign);
  241.         count++;
  242.     }
  243.  
  244.     if (!leftjust)
  245.         for (i = 0; i < leading; i++)
  246.         {
  247.          (*func) (fill);
  248.          count++;
  249.         }
  250.  
  251.     if ((sign == '-' || sign == '+') && fill == ' ')
  252.     {
  253.         (*func) (sign);
  254.         count++;
  255.     }
  256.  
  257.     for (i = 0; i < length; i++)
  258.     {
  259.          (*func) (str [i]);
  260.          count++;
  261.     }
  262.  
  263.     if (leftjust)
  264.         for (i = 0; i < leading; i++)
  265.         {
  266.          (*func) (fill);
  267.          count++;
  268.         }
  269.    }
  270. }
  271.  
  272. void _prt10 (unsigned num, char *str)
  273. {
  274.    int i;
  275.    char temp [6];
  276.  
  277.    temp [0] = '\0';
  278.  
  279.    for (i = 1; i <= 5; i++)
  280.    {
  281.     temp [i] = num % 10 + '0';
  282.     num /= 10;
  283.    }
  284.  
  285.    for (i = 5; temp [i] == '0'; i--)
  286.     ;
  287.  
  288.    if (i == 0)
  289.        i++;
  290.  
  291.    while (i >= 0)
  292.       *str++ = temp [i--];
  293. }
  294.  
  295. void _prtl10 (unsigned long num, char *str)
  296. {
  297.    int i;
  298.    char temp [11];
  299.  
  300.    temp [0] = '\0';
  301.  
  302.    for (i = 1; i <= 10; i++)
  303.    {
  304.     temp [i] = num % 10 + '0';
  305.     num /= 10;
  306.    }
  307.  
  308.    for (i = 10; temp [i] == '0'; i--)
  309.     ;
  310.  
  311.    if (i == 0)
  312.        i++;
  313.  
  314.    while (i >= 0)
  315.       *str++ = temp [i--];
  316. }
  317.  
  318. void _prt16 (unsigned num, char *str, int hexcase)
  319. {
  320.    int i;
  321.    char temp [5];
  322.    char *hexdigits;
  323.    char *hexdigits1 = "0123456789abcdef";
  324.    char *hexdigits2 = "0123456789ABCDEF";
  325.  
  326.    temp [0] = '\0';
  327.    hexdigits = (hexcase == 'U') ? hexdigits2 : hexdigits1;
  328.  
  329.    for (i = 1; i <= 4; i++)
  330.    {
  331.     temp [i] = hexdigits [num & 15];
  332.     num >>= 4;
  333.    }
  334.  
  335.    for (i = 4; temp [i] == '0'; i--)
  336.     ;
  337.  
  338.    if (!i)
  339.        i++;
  340.  
  341.    while (i >= 0)
  342.       *str++ = temp [i--];
  343. }
  344.  
  345. void _prtl16 (unsigned long num, char *str, int hexcase)
  346. {
  347.    int i;
  348.    char temp [9];
  349.    char *hexdigits;
  350.    char *hexdigits1 = "0123456789abcdef";
  351.    char *hexdigits2 = "0123456789ABCDEF";
  352.  
  353.    temp [0] = '\0';
  354.    hexdigits = (hexcase == 'U') ? hexdigits2 : hexdigits1;
  355.  
  356.    for (i = 1; i <= 8; i++)
  357.    {
  358.     temp [i] = hexdigits [num & 15];
  359.     num >>= 4;
  360.    }
  361.  
  362.    for (i = 8; temp [i] == '0'; i--)
  363.     ;
  364.  
  365.    if (!i)
  366.        i++;
  367.  
  368.    while (i >= 0)
  369.       *str++ = temp [i--];
  370. }